package cn.iocoder.yudao.module.design.service.houseUserRel;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.design.controller.admin.house.vo.HouseTaskStaticResVO;
import cn.iocoder.yudao.module.design.controller.admin.house.vo.HouseTwoUserReqVO;
import cn.iocoder.yudao.module.design.controller.admin.houseUserRel.vo.*;
import cn.iocoder.yudao.module.design.convert.houseUserRel.HouseUserRelConvert;
import cn.iocoder.yudao.module.design.dal.dataobject.houseUserRel.HouseUserRelDO;
import cn.iocoder.yudao.module.design.dal.dataobject.userflowrel.UserFlowRelDO;
import cn.iocoder.yudao.module.design.dal.mysql.houseUserRel.HouseUserRelMapper;
import cn.iocoder.yudao.module.design.dal.mysql.userflowrel.UserFlowRelMapper;
import cn.iocoder.yudao.module.design.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.design.enums.design.UserRelStatusCdEnum;
import cn.iocoder.yudao.module.design.enums.user.DesignUserRoleEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.design.enums.ErrorCodeConstants.HOUSE_USER_REL_NOT_EXISTS;
import static cn.iocoder.yudao.module.design.enums.ErrorCodeConstants.RELATION_DATA_IN_HOUSE_EXIST;

/**
 * 住宅相关用户关联 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class HouseUserRelServiceImpl implements HouseUserRelService {

    @Resource
    private HouseUserRelMapper houseUserRelMapper;

    @Resource
    private UserFlowRelMapper userFlowRelMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createHouseUserRel(HouseUserRelCreateReqVO createReqVO) {
        // 插入
        HouseUserRelDO houseUserRel = HouseUserRelConvert.INSTANCE.convert(createReqVO);
        houseUserRel.setDeleted(false);
        houseUserRelMapper.insert(houseUserRel);
        // 返回
        return houseUserRel.getId();
    }

    @Override
    public void updateHouseUserRel(HouseUserRelUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateHouseUserRelExists(updateReqVO.getId());
        // 更新
        HouseUserRelDO updateObj = HouseUserRelConvert.INSTANCE.convert(updateReqVO);
        houseUserRelMapper.updateById(updateObj);
    }

    @Override
    public void deleteHouseUserRel(Long id) {
        // 校验存在
        this.validateHouseUserRelExists(id);
        // 删除
        houseUserRelMapper.deleteById(id);
    }

    private void validateHouseUserRelExists(Long id) {
        if (houseUserRelMapper.selectById(id) == null) {
            throw exception(HOUSE_USER_REL_NOT_EXISTS);
        }
    }

    @Override
    public HouseUserRelDO getHouseUserRel(Long id) {
        return houseUserRelMapper.selectById(id);
    }

    /**
     * 获得住宅相关用户关联
     *
     * @param houseId
     * @return 住宅相关用户关联
     */
    @Override
    public HouseUserRelDO getHouseUserRelByHouseIdAndRoleId(Long houseId, Long roleId) {

        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("house_id", houseId);
        queryWrapper.eq("role_id", roleId);
        queryWrapper.eq("deleted", "0");
        queryWrapper.eq("status", UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode());
        return houseUserRelMapper.selectOne(queryWrapper);
    }

    @Override
    public void validateUserIsRole(Long houseId, long userId, Long roleId) {
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("house_id", houseId);

        if(ObjectUtil.isNotEmpty(roleId)){
            queryWrapper.eq("role_id", roleId);
        }

        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("deleted", "0");
        queryWrapper.in("status", "0","1");
        if (houseUserRelMapper.selectCount(queryWrapper)<=0) {
            throw exception(RELATION_DATA_IN_HOUSE_EXIST);
        }
    }
    /**
     * 校验项目内业主和设计师是否存在
     */
    @Override
    public void validateRoleInHouse(Long houseId,Long roleId) {
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("house_id", houseId);

        queryWrapper.in("role_id", roleId);
        queryWrapper.eq("deleted", "0");
        queryWrapper.in("status", "0","1");
        if (houseUserRelMapper.selectCount(queryWrapper)<=0) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.DESIGN_AND_OWNER_IN_HOUSE_EXIST, DesignUserRoleEnum.getRoleNameByRoleId(roleId));
        }
    }


    /**
     * 获得住宅相关用户关联
     *
     * @param houseId
     * @return 住宅相关用户关联
     */
    @Override
    public HouseUserRelDO getHouseUserRelByHouseIdAndUserId(Long houseId, Long userId) {

        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("house_id", houseId);
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("deleted", "0");
        queryWrapper.in("status", "0", "1");
        return houseUserRelMapper.selectOne(queryWrapper);
    }

    /**
     * @param houseId
     * @param userId
     * @return
     */
    @Override
    public List<String> getHouseRolesByHouseIdAndUserId(Long houseId, Long userId) {

        return houseUserRelMapper.getHouseRolesByHouseIdAndUserId(houseId, userId);
    }

    @Override
    public List<HouseTaskStaticResVO> getHouseTaskStatic(Long id) {

        List<HouseTaskStaticResVO> res = houseUserRelMapper.getHouseTaskStaticByUserId(id);
        return null;
    }

    @Override
    public List<HouseUserRelDO> getHouseUserRelList(Collection<Long> ids) {
        return houseUserRelMapper.selectBatchIds(ids);
    }

    /**
     * 获得住宅相关用户关联列表
     *
     * @param houseUserRelDO@return 住宅相关用户关联列表
     */
    @Override
    public List<HouseUserRelDO> getHouseUserRelList(HouseUserRelDO houseUserRelDO) {
        return houseUserRelMapper.selectList(houseUserRelDO);
    }

    @Override
    public PageResult<HouseUserRelDO> getHouseUserRelPage(HouseUserRelPageReqVO pageReqVO) {
        return houseUserRelMapper.selectPage(pageReqVO);
    }

    @Override
    public List<HouseUserRelDO> getHouseUserRelList(HouseUserRelExportReqVO exportReqVO) {
        return houseUserRelMapper.selectList(exportReqVO);
    }

    /**
     * 获取项目关联人员信息
     *
     * @param vo
     * @return
     */
    @Override
    public List<UserRelListVO> getUserRelList(HouseUserRelBaseVO vo) {
        Long roleId = ObjectUtil.isEmpty(vo.getRoleId()) ? null : Long.valueOf(vo.getRoleId());
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        return houseUserRelMapper.getHouseUserRelListByHouseIdAndRoleId(vo.getHouseId(), roleId,loginUserId);
    }

    /**
     * 获取项目关联人员信息
     *
     * @param
     * @return
     */
    @Override
    public List<UserRelListVO> getUserRelList(Long houseId, Long roleId) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        return houseUserRelMapper.getHouseUserRelListByHouseIdAndRoleId(houseId, roleId,loginUserId);

    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveHouseUserRel(Long houseId, Long userId, Long roleId) {
        saveHouseUserRel( houseId,  userId,  roleId, null);
    }
    /**
     * 保存单个项目关联人
     *
     * @author Annie
     * @time 2023/9/27 15:50
     * @param[1] houseId
     * @param[2] userId
     * @param[3] roleId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveHouseUserRel(Long houseId, Long userId, Long roleId,Integer statusCd) {
        // 默认状态 待处理
        Integer status = UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode();

        // 保存或更新判断用户 角色 项目是否已经关联 关联且和请求角色相同则不添加 ,角色不同 存在已经同意的记录直接通过
        // 改为null 判断全部
        List<HouseUserRelDO> houseUserRelDOList = queryHouseUserRelExits(houseId, userId, null);
        if ( houseUserRelDOList.size() > 0) {
            // 过滤关联角色
            Set<Long> distinctRoleIdSet = houseUserRelDOList.stream()
                    .map(HouseUserRelDO::getRoleId)
                    .collect(Collectors.toSet());
            // 过滤关联状态
            Set<String> distinctStatusSet = houseUserRelDOList.stream()
                    .map(HouseUserRelDO::getStatus)
                    .collect(Collectors.toSet());

            // 角色已经存在则跳过
            if (distinctRoleIdSet.contains(roleId)) {
                return;
            } else if (distinctStatusSet.contains(UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString())) {
                // 同一个用户已经同意加入项目 则直接同意
                status = UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode();
            }

        } else {
            String loginUserid = SecurityFrameworkUtils.getLoginUserId().toString();
            // 判断 录入人是否是本人 本人的话 status =1
            boolean loginUserEq = loginUserid.equals(userId.toString());
            status = loginUserEq ?
                    UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode() : UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode();
        }

        if(ObjectUtil.isNotEmpty(statusCd)){
            status = statusCd;
        }
        // 移除当前角色内其他用户
        deleteHouseUseRel(houseId,roleId);
        // 保存关联记录
        HouseUserRelDO houseUserRel = new HouseUserRelDO();
        houseUserRel.setHouseId(houseId);
        houseUserRel.setUserId(userId);
        houseUserRel.setStatus(String.valueOf(status));
        houseUserRel.setDeleted(false);
        houseUserRel.setRoleId(roleId);
        houseUserRelMapper.insert(houseUserRel);
        // TODO 保存操作 记录日志 等项目启动后一起发flowTask 任务

    }

    /**
     * 查询步骤2 关联人信息
     *
     * @param houseId
     * @return List<HouseTwoUserReqVO>
     * @throws
     * @author Annie
     * @time 2023/10/8 10:42
     * @param[1] houseId
     */
    @Override
    public List<HouseTwoUserReqVO> getHouseTwoUserList(Long houseId,List<Long> roleList) {

        return   houseUserRelMapper.getHouseTwoUserList(houseId,roleList);
    }

    /**
     * 移除预处理角色
     *
     * @param houseId
     * @param roleId
     * @throws
     */
    @Override
    public void deleteHouseUseRel(Long houseId, Long roleId) {
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<HouseUserRelDO>();
        queryWrapper.eq("house_id",houseId);
        queryWrapper.eq("role_id",roleId);
        queryWrapper.in("status",UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode(),
                UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode());
        houseUserRelMapper.delete(queryWrapper);
    }

    @Override
    public List<HouseTwoUserReqVO> getHouseTwoUserList(Long houseId ) {

        return getHouseTwoUserList( houseId,null);
    }
    /**
     * 查询 用户和项目是否有有效的关联记录
     *
     * @return boolean
     * @param[1] houseId
     * @param[2] userId
     */
    public List<HouseUserRelDO> queryHouseUserRelExits(Long houseId, Long userId, Long roleId) {
        // 判断userId和当前项目是否关联 如果已经关联状态 是待发起则状态一样为0   待同意好友后一起处理为1;
        // 查询是否存在已同意 记录  有则状态为 1（同意）  无则默认为0（待处理）
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<HouseUserRelDO>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.in("status", UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode(), UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode());
        queryWrapper.eq("house_id", houseId);
        return houseUserRelMapper.selectList(queryWrapper);

    }

    /**
     * 查询项目中是否有角色存在有效的关联记录
     *
     * @return boolean
     * @param[1] houseId
     * @param[2] userId
     */
    public  Long queryHouseUserRelRoleExits(Long houseId, Long roleId) {
        // 判断userId和当前项目是否关联 如果已经关联状态 是待发起则状态一样为0   待同意好友后一起处理为1;
        // 查询是否存在已同意 记录  有则状态为 1（同意）  无则默认为0（待处理）
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<HouseUserRelDO>();
        queryWrapper.eq("role_id", roleId);
        queryWrapper.in("status", UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode(), UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode());
        queryWrapper.eq("house_id", houseId);
        return houseUserRelMapper.selectCount(queryWrapper);

    }

    @Override
    public List<HouseUserRelDO> getHouseUserRelByHouseIdAndUserIdAndRoleId(Long houseId, Long userId, Long roleId) {
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<HouseUserRelDO>();
        queryWrapper.eq("house_id",houseId);
        queryWrapper.eq("role_id",roleId);
        queryWrapper.eq("user_id",roleId);
        queryWrapper.in("status","0","1");

        return       houseUserRelMapper.selectList(queryWrapper);
    }


    public void deleteUserFlowRel(Long houseId,Long flowId,Long userId){
        QueryWrapper<UserFlowRelDO> queryWrapper = new QueryWrapper<UserFlowRelDO>();
        queryWrapper.eq("house_id",houseId);
        queryWrapper.eq("flow_id",flowId);
        queryWrapper.eq("user_id",userId);
        userFlowRelMapper.delete(queryWrapper);
    }


    /**
     * 获取项目关联人员信息
     *
     * @param vo
     * @return
     */
    @Override
    public List<UserRelListVO> getUserRelGroupConcatList(Long houseId) {

        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        List<UserRelListVO> resultList =  houseUserRelMapper.getHouseUserRelListGroupConcatRoleName(houseId, null,loginUserId);
        // 对resultList  进行处理  根据userId相同的只保留一条数据 将角色名称拼接 其他保持不变

        Map<Long, List<String>> userIdRoleMap = resultList.stream()
                .collect(Collectors.groupingBy(UserRelListVO::getUserId,
                        Collectors.mapping(UserRelListVO::getRoleName, Collectors.toList())));


        Set<Long> uniqueUserIds = new HashSet<>();

        List<UserRelListVO> filteredUserRelList = new ArrayList<>();

        for (UserRelListVO user : resultList) {
            if (uniqueUserIds.add(user.getUserId())) {
                // If the user id is unique, add the user to the filtered list
                filteredUserRelList.add(user);
            }
        }

        for (UserRelListVO user : filteredUserRelList) {
            List<String> distinctRoles = userIdRoleMap.get(user.getUserId()).stream().distinct().collect(Collectors.toList());
            user.setRoleName(String.join(", ", distinctRoles));
        }

        return filteredUserRelList;
    }
}
